package com.example.lte.api;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.lte.config.BusinessLogic;
import com.example.lte.config.SysBusinessUnitEnum;
import com.example.lte.po.LoginPO;
import com.example.lte.po.PermPO;
import com.example.lte.po.ReqDevice;
import com.example.lte.po.VerifyCodePO;
import com.example.lte.restful.APIException;
import com.example.lte.restful.ResultCodeEnum;
import com.example.lte.service.IAsyncService;
import com.example.lte.service.IUserService;
import com.example.lte.service.LoginLogServiceImpl;
import com.example.lte.util.DeviceUtil;
import com.example.lte.util.IpUtils;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.OperatingSystem;
import eu.bitwalker.useragentutils.UserAgent;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author liuzh
 */
@RestController
@Api(tags = "登录模块")
public class LoginController {
    @Autowired
    private IUserService iUserService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private DefaultKaptcha defaultKaptcha;

    @Autowired
    private IAsyncService iAsyncService;

    @Autowired
    private LoginLogServiceImpl loginLogService;






    @GetMapping("/captcha")
    @BusinessLogic(value = "获取验证码",businessUnit = SysBusinessUnitEnum.LOGIN_UNIT)
    public VerifyCodePO getVerifyCode(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {
        UUID uuid = UUID.randomUUID();
        String verifyKey = "captcha_" + uuid;
        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
        try {
            //生产验证码字符串并保存到 redis 中
            String createText = defaultKaptcha.createText();
            System.out.println("验证码: " + createText );
            //验证码有效期60秒
            stringRedisTemplate.opsForValue().set(verifyKey, createText, 60, TimeUnit.SECONDS);
            // 使用生成的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中
            BufferedImage challenge = defaultKaptcha.createImage(createText);
            ImageIO.write(challenge, "jpg", jpegOutputStream);
        } catch (IllegalArgumentException e) {
            throw new APIException(ResultCodeEnum.VERITY_GEN_ERROR);
        }
        // 对字节数组Base64编码
        BASE64Encoder base64Encoder = new BASE64Encoder();
        String base64 = base64Encoder.encode(jpegOutputStream.toByteArray());
        String captchaBase64 = "data:image/jpeg;base64," + base64.replaceAll("\r\n", "");
        return VerifyCodePO.builder()
                .base64Captcha(captchaBase64)
                .uuidCaptcha(uuid.toString())
                .build();
    }


    @GetMapping("/login")
    @BusinessLogic(value = "登录系统",businessUnit = SysBusinessUnitEnum.LOGIN_UNIT)
    public LoginPO login(String uuid, String verifyCode, String account, String pwd,HttpServletRequest request) {
        if (StringUtils.isEmpty(uuid) || StringUtils.isEmpty(verifyCode)) {
            throw new APIException(ResultCodeEnum.VERITY_IDENTITY_ERROR);
        }
        String verifyKey = "captcha_" + uuid;
        String redisVerifyCode = stringRedisTemplate.opsForValue().get(verifyKey);
        assert redisVerifyCode != null;
        if (!StringUtils.pathEquals(verifyCode, redisVerifyCode)) {
            throw new APIException(ResultCodeEnum.VERITY_IDENTITY_ERROR);
        }
        String clientIp = IpUtils.getIpAddr(request);
        ReqDevice reqDevice = DeviceUtil.getReqDevice(request);
        return iUserService.doLogin(account, pwd,clientIp,reqDevice);
    }


    @GetMapping("/logout")
    @BusinessLogic(value = "注销退出",businessUnit = SysBusinessUnitEnum.LOGIN_UNIT)
    public String logout(@RequestHeader("Authorization") String token  ) {
        StpUtil.logout();
        loginLogService.delByLoginToken(token);
        return "logout success";
    }


    @DeleteMapping("/forceLogout")
    @BusinessLogic(value = "强制下线",businessUnit = SysBusinessUnitEnum.LOGIN_UNIT)
    public String forceLogout(@RequestParam String reqToken){
        //清空redis
        if (StpUtil.getLoginIdByToken(reqToken) != null){
            StpUtil.logoutByLoginId(StpUtil.getLoginIdByToken(reqToken));
        }
        //清除该token的登录日志
        loginLogService.delByLoginToken(reqToken);
        return "强制下线成功";
    }


    /**
     * {
     * "userId": 5,
     * "roleIds": [   //1个用户可对应多角色
     * 1,
     * 4
     * ],
     * "menuEntitySet": [    //合并多角色的菜单
     * {
     * "menuId": 2,
     * "note": "用户管理",
     * "routerName": "AccountManage",
     * "routerPath": "/accountManage",
     * "routerComponent": "AccountManage"
     * },
     * {
     * "menuId": 1,
     * "note": "个人中心",
     * "routerName": "Personal",
     * "routerPath": "/personal",
     * "routerComponent": "Personal"
     * }
     * ],
     * "buttonEntitySet": [   //合并多角色的按钮
     * {
     * "buttonId": 3,
     * "buttonName": "addAccount",
     * "note": "新增"
     * },
     * {
     * "buttonId": 4,
     * "buttonName": "delAccount",
     * "note": "删除"
     * },
     * {
     * "buttonId": 2,
     * "buttonName": "editAccount",
     * "note": "编辑"
     * },
     * {
     * "buttonId": 1,
     * "buttonName": "editPersonal",
     * "note": "编辑"
     * }
     * ]
     * }
     *
     * @param userId
     * @return
     */
    @GetMapping("/getPremByUserId")
    @BusinessLogic(value = "获取角色菜单",businessUnit = SysBusinessUnitEnum.LOGIN_UNIT)
    public PermPO getPremByUserId(Long userId) {
        return iUserService.getPremByUserId(userId);
    }

    @GetMapping("sendToFront")
    public String sendToFront(Long userId,HttpServletRequest request){
        String userAgent = request.getHeader("user-agent");
        String content ="<b>登录设备:</b>&nbsp;&nbsp;"+getDevice(userAgent);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("isLogin",true);
        jsonObject.put("loginTime",new Date());
        jsonObject.put("content",content);
        String msgUrl = "/topic/welcomInfo/"+userId;
        iAsyncService.sendWebsocketMsgBox(msgUrl,jsonObject.toJSONString());
        return "手动推送websocket";
    }

    private String getDevice(String userAgent) {
        //解析agent字符串
        UserAgent ua = UserAgent.parseUserAgentString(userAgent);
        //获取浏览器对象
        Browser browser = ua.getBrowser();
        //获取操作系统对象
        OperatingSystem os = ua.getOperatingSystem();
        return String.format("设备类型:%s,操作系统:%s,浏览器:%s,浏览器版本:%s,浏览器引擎:%s,用户代理(User-Agent):[%s]",
                os.getDeviceType(),
                os.getName(),
                browser.getName(),
                browser.getVersion(userAgent),
                browser.getRenderingEngine(),
                userAgent
        );
    }


}
